<?php

/**
 * ngValidatorRichDate validates a date. It also converts the input value to a valid date.
 *
 * @package    symfony
 * @subpackage validator
 * @author     Gabor Kormany <kormanyg@netgral.com>
 * @version    SVN: $Id: sfValidatorDate.class.php 13278 2008-11-23 15:04:24Z FabianLange $
 */
class ngValidatorRichDate extends sfValidatorDate
{
	/**
   * Configures the current validator.
   *
   * Available options:
   *
   *  * date_format:             A regular expression that dates must match
   *  * with_time:               true if the validator must return a time, false otherwise
   *  * date_output:             The format to use when returning a date (default to Y-m-d)
   *  * datetime_output:         The format to use when returning a date with time (default to Y-m-d H:i:s)
   *  * date_format_error:       The date format to use when displaying an error for a bad_format error (use date_format if not provided)
   *  * max:                     The maximum date allowed (as a timestamp)
   *  * min:                     The minimum date allowed (as a timestamp)
   *  * date_format_range_error: The date format to use when displaying an error for min/max (default to d/m/Y H:i:s)
   *  * delimiter:               The delimiter used in the textual format ( d.m.y, d-m-y )
   *  * holiday_check:           if true, triggers error when the date is a holiday (defaults to true)
   *
   * Available error codes:
   *
   *  * bad_format
   *  * min
   *  * max
   *
   * @param array $options    An array of options
   * @param array $messages   An array of error messages
   *
   * @see sfValidatorBase
   */
  protected function configure($options = array(), $messages = array())
  {
  	parent::configure( $options, $messages );
    $this->addOption('delimiter', '.' );
    $this->addOption('holiday_check', false );
    $this->addOption('date_format', "/^(?<year>[\d]{1,})\.(?<month>[\d]{1,})\.(?<day>[\d]{1,})\.{0,1}/" );
    $this->addMessage('bad_format', 'Does not match the date format.');
        
    $this->addMessage('holiday', sfContext::getInstance()->getI18N()->__('The date %value% is a holiday.') );
        
    foreach( $messages as $key => $value )
    {
      $this->addMessage( $key, $value );
    }  
  }

  protected function doClean($value)
  {
  	$value = str_replace('-', '.', $value);
	$value = str_replace(',', '.', $value);
    if ( preg_match( "/^(?<month>[\d]{2,})(?<day>[\d]{2,}$)/", $value, $results ) )
    {
    	$date = getdate();
    	$value = $date['year'].".".$results['month'].".".$results['day'].".";
    }
    
    if ( preg_match( "/^(?<month>[\d]{1,}).(?<day>[\d]{1,})[\.]{0,1}$/", $value, $results ) )
    {
     $date = getdate();
     $value = $date['year'].".".$results['month'].".".$results['day'].".";
    }    

    $clean = parent::doClean( $value );

    
    if( !preg_match( "/\.$/", $value ) )
      $value .= ".";

    $date = getdate( strtotime( $clean ) );

    
    if($this->getOption('holiday_check'))
    {
	    if( $date['wday'] <= 5 && $date['wday'] >= 1 )
	    {
	      $c = new Criteria();
	      $c->add( HolidayPeer::DATE, $clean, Criteria::EQUAL );
	      if ( HolidayPeer::doSelectOne( $c ) )
	        throw new sfValidatorError($this, 'holiday', array( 'value' => $value, 'holiday' => date($this->getOption('date_format_range_error'), $this->getOption('holiday'))));
	    }
	    else 
	    {
	      $c = new Criteria();
	      $c->add( WorkdayPeer::DATE, $clean, Criteria::EQUAL );
	      
	      if ( !WorkdayPeer::doSelectOne( $c ) )
	        throw new sfValidatorError($this, 'holiday', array( 'value' => $value, 'holiday' => date($this->getOption('date_format_range_error'), $this->getOption('holiday'))));    	
	    }
    } 
    
    
    return $clean;
  }
}
